#ifndef log_h
#define log_h

#include "oct_toolkits.h"

namespace oct_log
{

	class log_imp : public oct_toolkits::ilog
	{
	public:
		explicit log_imp();
		virtual ~log_imp();



		///  --------------------------------------------------------------------------------
		///  	初始化， 
		///  @info - 日志信息
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，日志文件路径不正确
		///				2 - 失败，如果磁盘空间剩余不够，则禁止创建日志文件对象
		///				3 - 失败，无法创建日志文件路径， 无法写入日志
		///				5 - 失败，创建日志文件失败，则无法写入日志
		///  --------------------------------------------------------------------------------
		virtual int init_(const oct_toolkits::st_log_info& info);


		///  --------------------------------------------------------------------------------
		///  写日志，日志内容为文本，且每一行前面都带有时间； 例如： [2021-03-28 15:00:00:001] 日志文件内容
		///  @str_log - 待写入日志文件内容
		///  @return - int	
		/// 			0 - 成功
		///				1 - 无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				2 - 失败，无法创建写日志文件对象，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_text_(const std::string& str_log);

		///  --------------------------------------------------------------------------------
		///  	写日志
		///  @pdata - 待写入内容
		///  @pdata_len - 待写入长度
		///  @return - int	
		/// 			0 - 成功、
		///				1 - 失败，参数【pdata】为空或者参数【pdata_len】为0
		///				2 - 失败，无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				3 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_text_(const char* pdata, unsigned int pdata_len);

		///  --------------------------------------------------------------------------------
		///  	将参数【str_log】每个字节的16进制写入文件，全部大写
		///  @str_log - 待写入内容
		///  @return - int	
		///				0 - 成功
		/// 			1 - 无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				2 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_hex_(const std::string& str_log);

		///  --------------------------------------------------------------------------------
		///  	将参数【pdata】每个字节的16进制写入文件，全部大写
		///  @pdata - 待写入内容
		///  @pdata_len - 写入内容长度
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，参数【pdata】为空或者参数【pdata_len】为0
		///				2 - 失败，无法写入日志，可能是日志文件创建失败，或者磁盘剩余空间不足5G
		///				3 - 失败，无法写入，日志文件读写对象创建失败，请先初始化
		///  --------------------------------------------------------------------------------
		virtual int log_hex_(const char* pdata, unsigned int pdata_len);


		///  --------------------------------------------------------------------------------
		///  	释放内部资源
		///  @return - void	
		/// 			
		///  --------------------------------------------------------------------------------
		virtual void uninit_();

	private:
		
		///  --------------------------------------------------------------------------------
		///  	将日志文件中的路径转为对应平台的方式
		///  @return - void	
		/// 			
		///  --------------------------------------------------------------------------------
		void get_real_path_();

		///  --------------------------------------------------------------------------------
		///  	创建日志存放的文件夹， 因为目录是多级， 可能存在中间的目录创建失败
		///  @return - bool	
		/// 			true - 路径创建成功
		///				false - 创建失败 
		///  --------------------------------------------------------------------------------
		bool create_log_path_();

		///  --------------------------------------------------------------------------------
		///  	创建目录
		///  @str_create - 
		///  @return - bool 
		/// 			false - 创建失败
		///				true - 创建成功
		///  --------------------------------------------------------------------------------
		bool create_dir_(const std::string str_create);

		///  --------------------------------------------------------------------------------
		///  	检查磁盘剩余空间
		///  @return - bool	
		/// 			
		///  --------------------------------------------------------------------------------
		bool check_disk_free_space_();

		///  --------------------------------------------------------------------------------
		///  	返回日志文件名
		///  @return - std::string	
		/// 			
		///  --------------------------------------------------------------------------------
		std::string get_log_file_name_();


		///  --------------------------------------------------------------------------------
		///  	log之前 先检查
		///  @cur_write - 当前需要写入的长度
		///  @return - bool	
		/// 			false _ 无法继续写文件，
		///				true - 可以继续写文件
		///  --------------------------------------------------------------------------------
		bool before_logging_(const unsigned long long cur_write);

		///  --------------------------------------------------------------------------------
		///  	创建日志文件
		///  @return - int	
		/// 			0 - 成功
		///				1 - 失败，创建失败
		///  --------------------------------------------------------------------------------
		int create_log_file_();

	private:
		/// 日志文件信息
		oct_toolkits::st_log_info	log_info_;

		/// 写日志文件
		oct_toolkits::ifile*		pfile_;

		/// 当前操作的日志文件
		std::string					cur_log_file_;

		/// 记录当前写入了多少字节了
		unsigned long long			has_written_bytes_;


		/// 工具库
		oct_toolkits::toolkits		kits_;

	};
}


#endif /// log_h